﻿/*
 * PIT Main Window
 */

#define _gpsspeed
#define _test

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.IO;
using EgeUniversity.SolarCarProject;

namespace Pit
{
	public partial class MainWindow : Window
	{
		//Cross Thread operations
		delegate void ChangeColorDelegate(Brush b);
		delegate void ChangeCarValueDelegate(string s);
		delegate void ChangeTextDelegate(TextBlock t, string s);
		//Pinarbasi GPS values
		//WARNING: Dublicate code
		const double GPSLeft	= 27.270942;
		const double GPSRight	= 27.27504;
		const double GPSTop		= 38.435069;
		const double GPSBottom	= 38.433657;

		public SolarCar Car { get; set; }
		//TCP/IP server
		public ServerClass Server { get; set; }

		DispatcherTimer timer; //Race time
		string data;
		//TimeSpan raceTime;
		//DateTime finishTime;

		//List<Point> SimGPS = new List<Point>();
		//List<double> SimVelocity = new List<double>();
		//List<double> SimSOC = new List<double>();
		//List<double> SimBatTemp = new List<double>();
		//List<double> SimPVTemp = new List<double>();
		//List<double> SimBatV = new List<double>();
		//List<double> SimBatCur = new List<double>();
		//List<double> SimPVV = new List<double>();
		//List<double> SimPVC = new List<double>();
		//int last = 0, lap = 0;

		public MainWindow()
		{
			InitializeComponent();
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			SetComponentTags();//Initializing

			//Create car
			Car = new SolarCar();
			Car.MapWidth = myCircuit.Width;
			Car.MapHeight = myCircuit.Height;
			SetCarValuesBindings();	//Set bindings

			//Create server
			Server = new ServerClass();
			Server.ConnectionChanged += new StatusChangedEventHandler(Server_ConnectionChanged);
			Server.DataRecieved += new DataRecievedEventHandler(Server_DataRecieved);
			Server.SetLocalIp();
			Server.Start(); //Start server

			//Set default GPS location
			Car.GPSLocation = new Point(GPSLeft, GPSBottom);

			timer = new DispatcherTimer();
			timer.Interval = TimeSpan.FromSeconds(1);
			timer.Tick += new EventHandler(timer_Tick);

			//new ControlWindow().Show();	//sahte veri girisi penceresi

			//using (StreamReader reader = new StreamReader("sim.txt"))
			//{
			//    while (!reader.EndOfStream)
			//    {
			//        string[] str = reader.ReadLine().Split('#');
			//        SimGPS.Add(new Point(Double.Parse(str[0]), Double.Parse(str[1])));
			//        SimVelocity.Add(Double.Parse(str[2]));
			//        SimSOC.Add(Double.Parse(str[3]));
			//        SimBatTemp.Add(Double.Parse(str[4]));
			//        SimPVTemp.Add(Double.Parse(str[5]));
			//        SimBatCur.Add(Double.Parse(str[6]));
			//        SimPVV.Add(Double.Parse(str[7]));
			//        SimPVC.Add(Double.Parse(str[8]));
			//        SimBatV.Add(Double.Parse(str[9]));
			//    }
			//}
		}

		private void SetCarValuesBindings()
		{
			Car.SetCarBinding(mySolarCarOnMap, Canvas.LeftProperty, "GPSOnMapX");
			Car.SetCarBinding(mySolarCarOnMap, Canvas.BottomProperty, "GPSOnMapY");
			Car.SetCarBinding(textGPS, TextBlock.TextProperty, "GPSLocation");

			Car.SetCarBinding(textAltitude, TextBlock.TextProperty, "Altitude");
#if _gpsspeed
			Car.SetCarBinding(progressSpeed, ProgressBar.ValueProperty, "Velocity");
#else
			Car.SetCarBinding(progressSpeed, ProgressBar.ValueProperty, "Velocity2");
#endif
			Car.SetCarBinding(progressBatterySOC, ProgressBar.ValueProperty, "BatteryStateOfCharge");
			Car.SetCarBinding(progressBatteryCurrent, ProgressBar.ValueProperty, "BatteryCurrent");
			Car.SetCarBinding(progressBatteryCurrentNegative, ProgressBar.ValueProperty, "BatteryCurrentNeg");
			Car.SetCarBinding(progressBatteryVoltage, ProgressBar.ValueProperty, "BatteryVoltage");
			Car.SetCarBinding(progressBatteryTemperature, ProgressBar.ValueProperty, "BatteryTemperature");
			Car.SetCarBinding(progressPV_Voltage1, ProgressBar.ValueProperty, "PVVoltage1");
			Car.SetCarBinding(progressPV_Voltage2, ProgressBar.ValueProperty, "PVVoltage2");
			Car.SetCarBinding(progressPV_Current1, ProgressBar.ValueProperty, "MotorCurrent");//PVCurrent1
			Car.SetCarBinding(progressPV_Current2, ProgressBar.ValueProperty, "PVCurrent2");
			Car.SetCarBinding(progressPVTemperature1, ProgressBar.ValueProperty, "MotorTemperature");//PVTemperature1
			Car.SetCarBinding(progressPVTemperature2, ProgressBar.ValueProperty, "PVTemperature2");
			Car.SetCarBinding(progressPVTemperature3, ProgressBar.ValueProperty, "PVTemperature3");

			Binding binding = new Binding();
			binding.Source = Car;
			binding.Path = new PropertyPath("BatteryCurrent");
			binding.Mode = BindingMode.OneWay;
			binding.StringFormat = "#0.0";
			textBatteryCurrent.SetBinding(TextBlock.TextProperty, binding);
		}

		int startIndex, lastIndex;
		void Server_DataRecieved(string e)
		{
			//Parse data and car values
			data += e;
			startIndex = data.LastIndexOf("$");
			lastIndex = data.IndexOf("\n", startIndex);

			if (startIndex >= 0 && lastIndex >= 0)
			{
				Car.Dispatcher.Invoke(
					new ChangeCarValueDelegate(ChangeCarValue),
					data.Substring(startIndex + 1, lastIndex - startIndex));
				data = String.Empty;
			}
		}

		void ChangeCarValue(string str)
		{
#if _test
			textInfo.Dispatcher.Invoke(
				new ChangeTextDelegate(ChangeText),
				textInfo,
				str);
#endif
			Car.SetCarValue(str);
		}

		void Server_ConnectionChanged(ConnectionStatus e)
		{//Connetion status changed
			if (e == ConnectionStatus.Connected)
				myConnectionStatus.Dispatcher.Invoke(
					new ChangeColorDelegate(ChangeColor),
					Brushes.Green);
			else
				myConnectionStatus.Dispatcher.Invoke(
					new ChangeColorDelegate(ChangeColor),
					Brushes.Red);
		}

		void ChangeColor(Brush b)
		{
			myConnectionStatus.Fill = b;
		}
		void ChangeText(TextBlock t, string s)
		{
			t.Text = s;
		}

		//int simindex = 0;
		void timer_Tick(object sender, EventArgs e)
		{//yaris saati
			//raceTime = (finishTime - DateTime.Now);
			//textTime.Content = raceTime.ToString("hh\\:mm\\:ss");
			//Car.GPSLocation = SimGPS[simindex];
			//Car.Velocity = SimVelocity[simindex];
			//Car.BatteryStateOfCharge = SimSOC[simindex];
			//Car.BatteryTemperature = SimBatTemp[simindex];
			//Car.PVTemperature = SimPVTemp[simindex];
			//Car.BatteryCurrent = SimBatCur[simindex];
			//Car.PVVoltage = SimPVV[simindex];
			//Car.PVCurrent = SimPVC[simindex];
			//Car.BatteryVoltage = SimBatV[simindex];

			//simindex++;
			//if (simindex >= SimGPS.Count)
			//{
			//    simindex = 0;
			//    lap++;
			//    if (lap > 50) lap = 0;
			//    textLap.Text = String.Format("{0}/50", lap);
			//}
			//textGPS.Text = String.Format("Enlem\t: {0:.000000}\nBoylam\t: {1:.000000}",
			//    Car.GPSLocation.Y, Car.GPSLocation.X);
			//textBatteryCurrent.Text = Car.BatteryCurrent.ToString(".0");
			//textAtabilecegiTur.Text = ": "+((int)(progressBatterySOC.Value * .4)).ToString();
		}

		private void Window_KeyDown(object sender, KeyEventArgs e)
		{
			//Only while developing
			switch (e.Key)
			{
				case Key.Up: Car.BatteryCurrent++; break;
				case Key.Down: Car.BatteryCurrent--; break;
			}

			if (e.Key == Key.Escape)
			{
				timer.Stop();
				App.Current.Shutdown();
			}
			else if (e.Key == Key.Enter)
			{
				//last = SimBatV.Count - 1;
				//int k = simindex - last;
				//double newSpeed = Double.Parse(textSim.Text);
				//for (int i = 1; i <= k; i++)
				//{
				//    SimBatV.Add(SimBatV[last] + (newSpeed - SimBatV[last]) / k * i);
				//}
				//Car.GPSLocation = new Point(27.272,38.434);
				//MessageBox.Show(String.Format("{0} ; {1}",
				//    Car.GPSOnMapX,
				//    Car.GPSOnMapY));
			}
			//else if (e.Key == Key.K)
			//{
			//    using (StreamWriter writer = new StreamWriter("sim.txt"))
			//    {
			//        for (int i = 0; i < SimPVTemp.Count; i++)
			//        {
			//            if (i < SimBatTemp.Count)
			//                writer.WriteLine(String.Format("{0}#{1}#{2}#{3}#{4}#{5}#{6}#{7}#{8}#{9}",
			//                    SimGPS[i].X.ToString(),
			//                    SimGPS[i].Y.ToString(),
			//                    SimVelocity[i],
			//                    SimSOC[i],
			//                    SimBatTemp[i],
			//                    SimPVTemp[i],
			//                    SimBatCur[i],
			//                    SimPVV[i],
			//                    SimPVC[i],
			//                    SimBatV[i]));
			//        }
			//        writer.Close();
			//    }
			//}

			//else if (e.Key == Key.F5)
			//{
			//    finishTime = DateTime.Now.AddHours(2);
			//    timer.Interval = TimeSpan.FromSeconds(0.1);
			//    if (timer.IsEnabled)
			//        timer.Stop();
			//    else
			//        timer.Start();
			//}
		}

		void SetComponentTags()
		{//Initializing
			progressSpeed.Tag				= CarValues.Velocity;
			progressBatterySOC.Tag			= CarValues.BatteryStateOfCharge;
			progressBatteryCurrent.Tag		= CarValues.BatteryCurrent;
			progressBatteryVoltage.Tag		= CarValues.BatteryVoltage;
			progressBatteryTemperature.Tag	= CarValues.BatteryTemperature;
			progressPV_Voltage1.Tag			= CarValues.PV_Voltage1;
			progressPV_Voltage2.Tag			= CarValues.PV_Voltage2;
			progressPV_Current1.Tag			= CarValues.PV_Current1;
			progressPV_Current2.Tag			= CarValues.PV_Current2;
			progressPVTemperature1.Tag		= CarValues.PV_Temperature1;
			progressPVTemperature2.Tag		= CarValues.PV_Temperature2;
			progressPVTemperature3.Tag		= CarValues.PV_Temperature3;
		}

		private void ProgressBars_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{//ProgressBar color depends on the values (Red, Green)
			ProgressBar pb = (ProgressBar)e.OriginalSource;

			if (pb != null && pb.Tag != null)
			{
				switch ((CarValues)pb.Tag)
				{
					case CarValues.BatteryStateOfCharge:
						if (e.OldValue < 30 && pb.Foreground != Brushes.Red)
							pb.Foreground = Brushes.Red;
						else if (e.NewValue > 30 && pb.Foreground != Brushes.Green)
							pb.Foreground = Brushes.Green;
						break;
					case CarValues.BatteryTemperature:
					case CarValues.PV_Temperature1:
					case CarValues.PV_Temperature2:
					case CarValues.PV_Temperature3:
						if (e.NewValue > 60 || e.NewValue < 20 && pb.Foreground != Brushes.Red)
							pb.Foreground = Brushes.Red;
						else if (e.NewValue < 60 && e.NewValue > 20 && pb.Foreground != Brushes.Green)
							pb.Foreground = Brushes.Green;
						break;
				}
			}
		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Server.ResetLocalIp();
		}
	}
}
